// Copyright (c) 2019 Presto Labs Pte. Ltd.
// Author: xguo, leon

#pragma once

#include "coin2/exchange/base/symbology/product.h"

namespace coin2::exchange::base::symbology {
template <typename CurrencyT, typename ProductT>
class IndexProduct : public CurrencyPairProduct<CurrencyT> {
 public:
  IndexProduct(
      const CurrencyT& base,
      const CurrencyT& quote,
      const std::string& order_native_symbol,
      const std::string& feed_native_symbol,
      const ExchangeType exchange)
      : CurrencyPairProduct<CurrencyT>(
            base,
            quote,
            ConvertToIndexNormStr(base, quote),
            order_native_symbol,
            ConvertToIndexNormStr(base, quote),
            feed_native_symbol,
            MarketType::Index,
            exchange) {}

 public:
  static std::unique_ptr<ProductT> FromNormStrImpl(
      const std::string& product_str,
      const int64_t resolve_timestamp) {
    std::string base_str;
    std::string quote_str;
    bool success = ParseIndexNormStr(
        product_str, &base_str, &quote_str);
    if (success) {
      auto base = CurrencyT::FromNormStrNoThrow(base_str, resolve_timestamp);
      auto quote = CurrencyT::FromNormStrNoThrow(quote_str, resolve_timestamp);
      if (base && quote) {
        return std::make_unique<ProductT>(*base, *quote);
      } else {
        return {};
      }
    } else {
      return {};
    }
  }

  IProduct* Clone() const final {
    auto* prod = new ProductT(
        CurrencyPairProduct<CurrencyT>::base_impl(),
        CurrencyPairProduct<CurrencyT>::quote_impl());
    prod->resolve_timestamp_ = this->resolve_timestamp();
    return prod;
  }

 private:
  static bool
  ParseIndexNormStr(
      const std::string currency_pair,
      std::string* base,
      std::string* quote) {
    std::vector<std::string> out;
    out = Split(currency_pair, "-.");
    if (out.size() != 3 || out[2] != "INDEX") {
      return false;
    }
    *base = out[0];
    *quote = out[1];
    return true;
  }

  static std::string ConvertToIndexNormStr(
      const ICurrency& base,
      const ICurrency& quote) {
    std::stringstream ss;
    ss << base.currency() << "-"
       << quote.currency() << ".INDEX";
    return ss.str();
  }
};
}  // namespace coin2::exchange::base::symbology
